package com.pap.product.calculate.agent.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.pap.base.service.impl.PapBaseServiceImpl;
import com.pap.base.util.date.DateUtils;
import com.pap.calculate.anysoft.formula.utilss.MyFormulaUtilss;
import com.pap.obj.vo.utils.StringLengthComparator;
import com.pap.product.agent.calculate.IProductCalculateAgent;
import com.pap.product.agent.calculate.dto.ProductCalculateDTO;
import com.pap.product.agent.calculate.dto.ProductItemCalculateDTO;
import com.pap.product.agent.calculate.dto.check.ProductCalculateCheckDTO;
import com.pap.product.agent.calculate.dto.check.ProductCalculateResponseDTO;
import com.pap.product.agent.product.dto.formuladefine.ProductItemDTO;
import com.pap.product.calculate.auto.entity.ProductCalculate;
import com.pap.product.calculate.auto.mapper.ProductCalculateMapper;
import com.pap.product.exception.MyCalculateException;
import com.pap.product.product.auto.mapper.ProductDetailMapper;

@Transactional
@Service("productCalculateAgent")
public class ProductCalculateAgentImpl extends PapBaseServiceImpl<ProductCalculate> implements IProductCalculateAgent {

	@Autowired
	private ProductCalculateMapper productCalculateMapper;

	@Autowired
	private ProductDetailMapper productDetailMapper;

	@Override
	public int saveOrUpdateCalculator(ProductCalculateDTO productCalculate, String clientLicenseId,
			String loginUserId) {
		productCalculateMapper.deleteByProductId(productCalculate.getProductId());
		List<ProductItemCalculateDTO> inputDetails = productCalculate.getDetails();
		if (inputDetails != null && inputDetails.size() > 0) {
			for (ProductItemCalculateDTO productItemCalculateDTO : inputDetails) {
				ProductCalculate temp = new ProductCalculate();
				temp.setId(UUID.randomUUID().toString());
				temp.setCode(productItemCalculateDTO.getCode());
				temp.setProductId(productCalculate.getProductId());
				temp.setItemId(productItemCalculateDTO.getId());
				temp.setItemCode(productItemCalculateDTO.getCode());
				temp.setItemName(productItemCalculateDTO.getName());
				temp.setItemType(productItemCalculateDTO.getItemType());
				temp.setFormula(productItemCalculateDTO.getFormula());
				temp.setOrderNo(productItemCalculateDTO.getOrderNo());
				temp.setCreateIp("0.0.0.0");
				temp.setCreateTime(DateUtils.getCurrDateTimeStr());
				temp.setCreateUser(loginUserId);
				temp.setClientLicenseId(clientLicenseId);
				mapper.insertSelective(temp);
			}
		}

		return 1;
	}

	@Override
	public List<ProductCalculateResponseDTO> calculate(String productId,
			List<ProductCalculateCheckDTO> inputCalculateList, String clientLicenseId, String loginUserId)
			throws MyCalculateException {
		List<ProductCalculateResponseDTO> returnDTOList = new ArrayList<ProductCalculateResponseDTO>();
		// 用来记录当前此产品下面所有融资项目的具体值
		Map<String, String> allProductDetailItemValueMap = new HashMap<String, String>();

		// 传递过来的，融资项目的具体值
		LinkedHashMap<String, String> inputBasicParamMap = calculateInputValue(inputCalculateList);
		// 当前产品中，定义的融资项目公式部分
		LinkedHashMap<String, String> calculateMap = productCalculateMap(productId);

		for (Map.Entry<String, String> calculate : calculateMap.entrySet()) {
			for (Map.Entry<String, String> basicParam : inputBasicParamMap.entrySet()) {
				calculate.setValue(calculate.getValue().replaceAll(
						basicParam.getKey().replaceAll("\\(", "\\\\(").replaceAll("\\)", "\\\\)"),
						basicParam.getValue()));
			}
			try {
				// 此时这里的calculate.getValue() 需要进行公式部分的计算
				Object formulaObj = MyFormulaUtilss.selfOperationResult(calculate.getValue());
				BigDecimal formulaBigDecimal = new BigDecimal(formulaObj.toString());
				calculateMap.put(calculate.getKey(),
						formulaBigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
				inputBasicParamMap.put(calculate.getKey(),
						formulaBigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
				allProductDetailItemValueMap.put(calculate.getKey(), calculate.getValue());
			} catch (Exception e) {
				throw new MyCalculateException(calculate.getValue(), e.getCause());
			}
		}

		System.out.println(allProductDetailItemValueMap);
		//
		for (Map.Entry<String, String> calculate : allProductDetailItemValueMap.entrySet()) {
			ProductCalculateResponseDTO temp = new ProductCalculateResponseDTO();
			temp.setCode(calculate.getKey());
			temp.setValue(calculate.getValue());
			returnDTOList.add(temp);
		}
		return returnDTOList;
	}

	/**
	 * 将传递过来的参数，进行便利循环，返回map集合 key 为 融资项目的编码，value为传递过来的融资项目值
	 * 需要注意，定义的公式里面，是存放的融资项目的编码
	 * 
	 * @param inputCalculateList
	 * @return
	 */
	private LinkedHashMap<String, String> calculateInputValue(List<ProductCalculateCheckDTO> inputCalculateList) {
		LinkedHashMap<String, String> inputCalculateValueMap = new LinkedHashMap<String, String>();
		if (inputCalculateList != null && inputCalculateList.size() > 0) {
			for (ProductCalculateCheckDTO productCalculateCheckDTO : inputCalculateList) {
				inputCalculateValueMap.put(productCalculateCheckDTO.getItemCode(),
						productCalculateCheckDTO.getMyInputValue());
			}
		}
		return inputCalculateValueMap;
	}

	/**
	 * 查询出来当前产品下面包含的所有融资项目code值
	 * 
	 * @return
	 */
	private TreeSet<String> productItemCodeTreeSet(String clientLicenseId, String productId) {
		TreeSet<String> treeSet = new TreeSet<String>(new StringLengthComparator());

		List<ProductItemDTO> productItemList = productDetailMapper.selectProductDetailItem(clientLicenseId, productId);
		if (productItemList != null && productItemList.size() > 0) {
			for (ProductItemDTO productItemDTO : productItemList) {
				// 存入融资项目编码，并且匹配左右括号，防止后续正则表达式替换功能失效
				treeSet.add(productItemDTO.getCode());
			}
		}
		return treeSet;
	}

	/**
	 * 此产品下面定义的产品公式集合，按照顺序号从小到大进行排序
	 * 
	 * @param productId
	 * @return
	 */
	private LinkedHashMap<String, String> productCalculateMap(String productId) {
		LinkedHashMap<String, String> calculateMap = new LinkedHashMap<String, String>();
		List<ProductCalculate> calculateList = productCalculateMapper.selectByProdocutIdOrderByOrderNo(productId);
		if (calculateList != null && calculateList.size() > 0) {
			for (ProductCalculate productCalculate : calculateList) {
				calculateMap.put(productCalculate.getCode(), productCalculate.getFormula());
			}
		}
		return calculateMap;
	}
}
